home *** CD-ROM | disk | FTP | other *** search
- /***********************************************************************
- *
- * PROJECT: PMake
- * MODULE: Prefix -- Mounting Routines
- * FILE: mount.c
- *
- * AUTHOR: Adam de Boor: Jul 5, 1989
- *
- * ROUTINES:
- * Name Description
- * ---- -----------
- * Mount_Init Initialize the module
- * Mount_Unmount Unmount an individual prefix.
- *
- * REVISION HISTORY:
- * Date Name Description
- * ---- ---- -----------
- * 7/ 5/89 ardeb Initial version
- *
- * DESCRIPTION:
- * Functions to deal with mounting a prefix
- *
- * Copyright (c) Berkeley Softworks 1989
- * Copyright (c) Adam de Boor 1989
- *
- * Permission to use, copy, modify, and distribute this
- * software and its documentation for any non-commercial purpose
- * and without fee is hereby granted, provided that the above copyright
- * notice appears in all copies. Neither Berkeley Softworks nor
- * Adam de Boor makes any representations about the suitability of this
- * software for any purpose. It is provided "as is" without
- * express or implied warranty.
- *
- ***********************************************************************/
- #ifndef lint
- static char *rcsid =
- "$Id: mount.c,v 1.9 89/10/10 00:35:50 adam Exp $";
- #endif lint
-
- #include "prefix.h"
- #include "rpc.h"
- #include "sunrpc.h"
-
- static int mountSock; /* Socket over which NFS requests for
- * MOUNT_DIR arrive */
-
- static struct nfsfattr mattr; /* Statistics for the mount directory */
-
- /***********************************************************************
- * Mount_Unmount
- ***********************************************************************
- * SYNOPSIS: Attempt to unmount a single prefix
- * THE PREFIX SHOULD HAVE BEEN CHECKED FOR LOCKS BEFORE
- * CALLING THIS PROCEDURE.
- * CALLED BY: ImportDelete, MountUnmountPrefix
- * RETURN: 0 if failed
- * SIDE EFFECTS: The node is shifted onto the prefixes list if
- * unmounted.
- * The serverName and remote fields are freed and
- * NULLed.
- * The unmount event is deleted and the field zeroed.
- *
- * STRATEGY:
- *
- * REVISION HISTORY:
- * Name Date Description
- * ---- ---- -----------
- * ardeb 7/ 8/89 Initial Revision
- *
- ***********************************************************************/
- int
- Mount_Unmount(pp, answerPtr)
- Prefix *pp; /* Prefix to unmount */
- char **answerPtr; /* Place to store failure message */
- {
- if (Child_Call(pp, PREFIX_UNMOUNT)) {
- pp->flags &= ~PREFIX_MOUNTED;
-
- /*
- * Nuke server data.
- */
- free(pp->serverName);
- free(pp->remote);
- pp->serverName = pp->remote = (char *)NULL;
-
- /*
- * Delete the event for unmounting it...
- */
- if (pp->unmount) {
- Rpc_EventDelete(pp->unmount);
- pp->unmount = (Rpc_Event)NULL;
- }
- /*
- * Announce our success
- */
- return(1);
- } else {
- *answerPtr = "prefix busy";
- return(0);
- }
- }
-
-
- /***********************************************************************
- * MountUnmountPrefix
- ***********************************************************************
- * SYNOPSIS: Attempt to remove a prefix.
- * CALLED BY: Rpc event
- * RETURN: FALSE (no need to stay awake)
- * SIDE EFFECTS: If the prefix is unmounted it is either moved
- * back to the prefixes list and the mount point
- * taken over or, if the prefix is labeled as
- * temporary, the prefix is freed.
- *
- * STRATEGY:
- *
- * REVISION HISTORY:
- * Name Date Description
- * ---- ---- -----------
- * ardeb 7/ 6/89 Initial Revision
- *
- ***********************************************************************/
- static int
- MountUnmountPrefix(pp, ev)
- Prefix *pp; /* Prefix to attempt to unmount */
- Rpc_Event ev; /* Event that caused us to be called */
- {
- char *reason;
-
- dprintf("unmount(%s)...", pp->path);
-
- if (PrefixIsLocked(pp)) {
- dprintf("locked\n");
- } else if (!Mount_Unmount(pp, &reason)) {
- /*
- * Still active -- leave it alone until the next interval
- * expires.
- */
- dprintf("%s\n", reason);
- } else if ((pp->flags & PREFIX_TEMP) == 0) {
- /*
- * Permanent prefix -- remount it on ourselves.
- */
- dprintf("successful: remounting prefix\n");
- Import_MountPrefix(pp);
- } else {
- dprintf("successful\n");
- }
- }
-
-
-
- /***********************************************************************
- * MountNullReq
- ***********************************************************************
- * SYNOPSIS: Let the caller know we're alive
- * CALLED BY: RFS_NULL
- * RETURN: SUNRPC_SUCCESS
- * SIDE EFFECTS: None
- *
- * STRATEGY:
- *
- * REVISION HISTORY:
- * Name Date Description
- * ---- ---- -----------
- * ardeb 9/10/89 Initial Revision
- *
- ***********************************************************************/
- static enum clnt_stat
- MountNullReq(remote, msg, args, res, data, resPtr)
- struct sockaddr_in *remote; /* Source of request */
- Rpc_Message msg; /* Message token */
- void *args; /* Arguments passed */
- void *res; /* Results to return */
- Rpc_Opaque data; /* Data we stored (UNUSED) */
- void **resPtr; /* Room for modified 'res' (UNUSED)*/
- {
- return(SUNRPC_SUCCESS);
- }
-
- /***********************************************************************
- * MountGetAttrReq
- ***********************************************************************
- * SYNOPSIS: Handle a GETATTR either on an entry we were given
- * by ImportReadLinkReq, or on the root of the
- * system itself.
- * CALLED BY: SunRpc
- * RETURN: SUNRPC_SUCCESS
- * SIDE EFFECTS: None.
- *
- * STRATEGY:
- *
- * REVISION HISTORY:
- * Name Date Description
- * ---- ---- -----------
- * ardeb 9/10/89 Initial Revision
- *
- ***********************************************************************/
- static enum clnt_stat
- MountGetAttrReq(remote, msg, args, res, data, resPtr)
- struct sockaddr_in *remote; /* Source of request */
- Rpc_Message msg; /* Message token */
- PrefixHandle *args; /* Arguments passed */
- struct nfsattrstat *res; /* Results to return */
- Rpc_Opaque data; /* Data we stored (UNUSED) */
- void **resPtr; /* Room for modified 'res' (UNUSED)*/
- {
- Prefix *pp;
-
- if (args->type == PH_SPECIAL) {
- /*
- * Need to tell the kernel this thing's a directory...
- */
- dprintf("GETATTR(%s)\n", MOUNT_DIR);
-
- res->ns_status = NFS_OK;
- res->ns_attr = mattr;
- } else {
- pp = HandleToPrefix((fhandle_t *)args);
-
- if (pp == PREFIX_STALE) {
- res->ns_status = NFSERR_STALE;
- } else {
- dprintf("MGETATTR(%s)\n", pp->path);
-
- res->ns_status = NFS_OK;
- /*
- * In this "directory", any other file is a symbolic
- * link back to its real prefix.
- */
- res->ns_attr = link_attr;
- res->ns_attr.na_size = strlen(pp->path);
- res->ns_attr.na_blocksize = pp->attr.na_blocksize;
- }
- }
- return(SUNRPC_SUCCESS);
- }
-
- /***********************************************************************
- * MountReadLinkReq
- ***********************************************************************
- * SYNOPSIS: Read one of our "symbolic links" -- this is our
- * signal to actually mount a prefix.
- * CALLED BY: SunRpc
- * RETURN: SUNRPC_SUCCESS if prefix mounted, SUNRPC_SYSTEMERR
- * if not.
- * SIDE EFFECTS: prefix is mounted.
- *
- * STRATEGY:
- *
- * REVISION HISTORY:
- * Name Date Description
- * ---- ---- -----------
- * ardeb 9/10/89 Initial Revision
- *
- ***********************************************************************/
- static enum clnt_stat
- MountReadLinkReq(remote, msg, args, res, data, resPtr)
- struct sockaddr_in *remote; /* Source of request */
- Rpc_Message msg; /* Message token */
- fhandle_t *args; /* Arguments passed */
- struct nfsrdlnres *res; /* Results to return */
- Rpc_Opaque data; /* Data we stored (UNUSED) */
- void **resPtr; /* Room for modified 'res' (UNUSED)*/
- {
- Prefix *pp;
- LstNode ln;
- struct sockaddr_in sin;
- struct timeval retry;
-
- pp = HandleToPrefix(args);
-
- dprintf("MREADLINK: ");
- if (pp == PREFIX_STALE) {
- dprintf("STALE\n");
- res->rl_status = NFSERR_STALE;
- } else if (PrefixIsLocked(pp)) {
- /*
- * If prefix is in flux, we don't want to try and mount it -- just
- * drop the request on the floor. Hopefully, when the kernel
- * retransmits its request the prefix will be stable again.
- *
- * Note that we can't just hang out here, as then the pending
- * request that we interrupted in an earlier frame won't be returned
- * to...
- */
- dprintf("LOCKED\n");
- return(SUNRPC_DONTRESPOND);
- } else if (pp->serverName == NULL) {
- /*
- * Couldn't find the server -- pretend there's nothing
- * here.
- */
- dprintf("server for '%s' unknown\n", pp->path);
- res->rl_status = NFSERR_NOENT;
- } else if (pp != NULL) {
- dprintf("MREADLINK(%s)\n", pp->path);
-
- res->rl_status = NFS_OK;
-
- if ((pp->flags & PREFIX_MOUNTED) == 0) {
- /*
- * Unmount our prefix and mount the real one.
- * Note that Child_Call takes care of any necessary locks on
- * the prefix.
- */
- struct timeval unmountTime;
-
- if (pp->flags & PREFIX_TEMP) {
- dprintf("%s: nothing to unmount\n", pp->path);
- } else {
- dprintf("unmount %s...", pp->path);
- if (!Child_Call(pp, PREFIX_UNMOUNT_LOCAL)) {
- return(RPC_SYSTEMERROR);
- }
- dprintf("successful\n");
- }
- dprintf("mount %s from %s...", pp->remote, pp->serverName);
-
- if (!Child_Call(pp, PREFIX_MOUNT)) {
- /*
- * Re-mount ourselves, if necessary, so the
- * user can try again later.
- */
- if ((pp->flags & PREFIX_TEMP) == 0) {
- Import_MountPrefix(pp);
- }
- return (RPC_SYSTEMERROR);
- } else {
- pp->flags |= PREFIX_MOUNTED;
- }
-
- dprintf("successful\n");
-
- /*
- * Create event for unmounting this prefix.
- */
- unmountTime.tv_sec = UNMOUNT_INTERVAL;
- unmountTime.tv_usec = 0;
-
- pp->unmount = Rpc_EventCreate(&unmountTime,
- MountUnmountPrefix,
- (Rpc_Opaque)pp);
- } else {
- dprintf("already mounted\n");
- }
-
- /*
- * Return a symbolic link back to the prefix...
- * Sets up return value at the end of the nfsrdlnres
- */
- res->rl_count = strlen(pp->path);
- res = (struct nfsrdlnres *)realloc(res, sizeof(*res)+res->rl_count);
- *resPtr = (void *)res;
- res->rl_data = (char *)(res+1);
- bcopy(pp->path, res->rl_data, res->rl_count);
- } else {
- dprintf("pp == NULL\n");
- res->rl_status = NFSERR_NOENT;
- }
-
- return(SUNRPC_SUCCESS);
- }
-
-
- /***********************************************************************
- * MountStatFSReq
- ***********************************************************************
- * SYNOPSIS: Another bogus STATFS handler, since this filesystem
- * doesn't exist either
- * CALLED BY: SunRpc for RFS_STATFS
- * RETURN: SUNRPC_SUCCESS
- * SIDE EFFECTS: None
- *
- * STRATEGY:
- *
- * REVISION HISTORY:
- * Name Date Description
- * ---- ---- -----------
- * ardeb 9/10/89 Initial Revision
- *
- ***********************************************************************/
- static enum clnt_stat
- MountStatFSReq(remote, msg, args, res, data, resPtr)
- struct sockaddr_in *remote; /* Source of request */
- Rpc_Message msg; /* Message token */
- fhandle_t *args; /* Arguments passed */
- struct nfsstatfs *res; /* Results to return */
- Rpc_Opaque data; /* Data we stored (UNUSED) */
- void **resPtr; /* Room for modified 'res' (UNUSED)*/
- {
- dprintf("STATFS(%s)\n", MOUNT_DIR);
-
- bzero(res, sizeof(*res));
-
- /*
- * Return bogus information for the filesystem for now
- */
- res->fs_status = NFS_OK;
- res->fs_tsize = res->fs_bsize = 8192;
- res->fs_blocks = 1;
- res->fs_bfree = 0;
- res->fs_bavail = 0;
-
- return(SUNRPC_SUCCESS);
- }
-
- /***********************************************************************
- * MountLookupReq
- ***********************************************************************
- * SYNOPSIS: Deal with a directory lookup in this filesystem
- * CALLED BY: SunRpc RFS_LOOKUP
- * RETURN: SUNRPC_SUCCESS
- * SIDE EFFECTS: None
- *
- * STRATEGY:
- *
- * REVISION HISTORY:
- * Name Date Description
- * ---- ---- -----------
- * ardeb 9/10/89 Initial Revision
- *
- ***********************************************************************/
- static enum clnt_stat
- MountLookupReq(remote, msg, args, res, data, resPtr)
- struct sockaddr_in *remote; /* Source of request */
- Rpc_Message msg; /* Message token */
- struct nfsdiropargs *args; /* Arguments passed */
- struct nfsdiropres *res; /* Results to return */
- Rpc_Opaque data; /* Data we stored (UNUSED) */
- void **resPtr; /* Room for modified 'res' (UNUSED)*/
- {
- Prefix *pp;
- PrefixHandle ph;
-
- /*
- * The name consists of two integers separated by a decimal point.
- * The first integer is the address of the Prefix involved, while the
- * second is the generation number for the prefix. We need to scan
- * them into a PrefixHandle structure for HandleToPrefix to use...
- */
- dprintf("MLOOKUP(%s)\n", args->da_name);
- ph.rd.type = PH_REGULAR;
- sscanf(args->da_name, "%d.%d", &ph.rd.pp, &ph.rd.generation);
- pp = HandleToPrefix((fhandle_t *)&ph);
-
- if (pp == PREFIX_STALE) {
- dprintf("\tSTALE HANDLE\n");
- res->dr_status = NFSERR_STALE;
- } else if (pp == NULL) {
- dprintf("\tNO SUCH PREFIX\n");
- res->dr_status = NFSERR_NOENT;
- } else {
- dprintf("\tMLOOKUP(%s)\n", pp->path);
- res->dr_status = NFS_OK;
-
- /*
- * Handle is same as always...
- */
- PrefixToHandle(pp, &res->dr_fhandle);
-
- /*
- * All prefixes are symbolic links until they're mounted.
- * (the thing can't be mounted or we wouldn't be here)
- */
- res->dr_attr = link_attr;
- res->dr_attr.na_size = strlen(pp->path);
- res->dr_attr.na_blocksize = pp->attr.na_blocksize;
- }
-
- return(SUNRPC_SUCCESS);
- }
-
-
- /***********************************************************************
- * Mount_Init
- ***********************************************************************
- * SYNOPSIS: Initialize things here
- * CALLED BY: main
- * RETURN: Nothing
- * SIDE EFFECTS: The mount directory is created and statted
- *
- * STRATEGY:
- *
- * REVISION HISTORY:
- * Name Date Description
- * ---- ---- -----------
- * ardeb 7/ 6/89 Initial Revision
- *
- ***********************************************************************/
- void
- Mount_Init()
- {
- struct stat stb;
-
- /*
- * Make sure special directory is around
- */
- (void)mkdir(MOUNT_DIR, 0555);
-
- /*
- * Fetch its attributes
- */
- if (stat(MOUNT_DIR, &stb) < 0) {
- perror(MOUNT_DIR);
- exit(1);
- }
-
- /*
- * Covert to NFS Normal Form
- */
- mattr.na_type = NFDIR;
- mattr.na_mode = 0555 | S_IFDIR;
- mattr.na_nlink = 1;
- mattr.na_uid = stb.st_uid;
- mattr.na_gid = stb.st_gid;
- mattr.na_size = stb.st_size;
- mattr.na_blocksize = stb.st_blksize;
- mattr.na_rdev = -1;
- mattr.na_blocks = stb.st_blocks;
- mattr.na_fsid = -1;
- mattr.na_nodeid = stb.st_ino;
- mattr.na_atime.tv_sec = stb.st_atime;
- mattr.na_atime.tv_usec = stb.st_spare1;
- mattr.na_mtime.tv_sec = stb.st_mtime;
- mattr.na_mtime.tv_usec = stb.st_spare2;
- mattr.na_ctime.tv_sec = stb.st_ctime;
- mattr.na_ctime.tv_usec = stb.st_spare3;
-
- /*
- * Create a socket for ourselves -- it can be anywhere in the UDP
- * address space.
- */
- mountSock = Rpc_UdpCreate(True, 0);
-
- /*
- * Register the Sun RPC servers for the socket. These are the only
- * NFS procedures we handle -- anything else generates a "procedure
- * unavailable" error.
- */
- SunRpc_ServerCreate(mountSock, NFS_PROGRAM, RFS_NULL, NFS_VERSION,
- MountNullReq, (Rpc_Opaque)NULL,
- 0, xdr_void, 0, xdr_void);
-
- SunRpc_ServerCreate(mountSock, NFS_PROGRAM, RFS_GETATTR, NFS_VERSION,
- MountGetAttrReq, (Rpc_Opaque)NULL,
- sizeof(fhandle_t), xdr_fhandle,
- sizeof(struct nfsattrstat), xdr_attrstat);
-
- SunRpc_ServerCreate(mountSock, NFS_PROGRAM, RFS_READLINK, NFS_VERSION,
- MountReadLinkReq, (Rpc_Opaque)NULL,
- sizeof(fhandle_t), xdr_fhandle,
- sizeof(struct nfsrdlnres), xdr_rdlnres);
-
- SunRpc_ServerCreate(mountSock, NFS_PROGRAM, RFS_LOOKUP, NFS_VERSION,
- MountLookupReq, (Rpc_Opaque)NULL,
- sizeof(struct nfsdiropargs), xdr_diropargs,
- sizeof(struct nfsdiropres), xdr_diropres);
-
- SunRpc_ServerCreate(mountSock, NFS_PROGRAM, RFS_STATFS, NFS_VERSION,
- MountStatFSReq, (Rpc_Opaque)NULL,
- sizeof(fhandle_t), xdr_fhandle,
- sizeof(struct nfsstatfs), xdr_statfs);
-
- }
-
-
- /***********************************************************************
- * Mount_MountRoot
- ***********************************************************************
- * SYNOPSIS: Use our child process to mount ourselves on MOUNT_DIR
- * CALLED BY: main
- * RETURN: True if successful.
- * SIDE EFFECTS: >?
- *
- * STRATEGY:
- *
- * REVISION HISTORY:
- * Name Date Description
- * ---- ---- -----------
- * ardeb 9/10/89 Initial Revision
- *
- ***********************************************************************/
- int
- Mount_MountRoot()
- {
- struct sockaddr_in sin;
- int addrlen = sizeof(sin);
-
- /*
- * Need to locate the port for the socket so Child_MountSpecial can
- * tell the kernel where we are.
- */
- if (getsockname(mountSock, &sin, &addrlen) < 0) {
- return(False);
- }
-
- /*
- * Now tell the child to mount us on MOUNT_DIR.
- */
- return(Child_MountSpecial(sin.sin_port, MOUNT_DIR));
- }
-